DevSecOps
Delivery practice for systems where a bad release can affect patient care. The techniques are the ordinary ones; the health-specific parts are the change control, the testing with realistic-but-not-real data, and the fact that many clinical platforms are long-lived and dependency-heavy.
Pipeline
commit
│
├─ lint, unit tests
├─ dependency scan (known vulnerabilities in libraries)
├─ secret scan (credentials committed by accident)
├─ SAST (static analysis)
│
build
├─ container image build
├─ image scan (OS and library CVEs)
├─ SBOM generation
├─ image signing
│
test
├─ integration tests against synthetic data
├─ FHIR profile validation / conformance suite
├─ DAST against a running instance
│
deploy
├─ staging → automated verification
├─ change approval (for clinical systems)
└─ production → progressive rollout, monitored, reversible
The two steps most often missing in health deployments are conformance testing — validating that what the system emits still matches the implementation guide — and a tested rollback.
Test data
Never production clinical data in a non-production environment. It is a disclosure, and it will end up on a laptop.
Options, in order of preference:
- Synthetic generation — Synthea produces realistic synthetic patient histories including FHIR bundles. The best default for functional testing.
- Purpose-built fixtures — hand-crafted cases covering the awkward scenarios: twins, name changes, estimated dates, merges, corrections.
- De-identified production data — only with a formal governance decision, documented re-identification risk assessment, and controls on the environment. See health data. Treat "de-identified" as a claim to be tested, not a property to be assumed.
Synthetic data has a limitation worth naming: it does not reproduce your population's naming conventions, data-entry error patterns or missingness. For tuning patient matching specifically, synthetic data is misleading, and a governed process using real data is necessary.
Infrastructure as code
All infrastructure defined in version-controlled code, applied through a pipeline, never by hand in a console.
| Tool | Role |
|---|---|
| Terraform / OpenTofu | Provisioning cloud and on-premises resources |
| Ansible | Configuration management, especially for VM-based deployments |
| Helm | Packaging Kubernetes applications |
| Argo CD / Flux | GitOps — the cluster converges on the declared state in Git |
| Kustomize | Environment overlays without templating |
Why it matters here specifically: national health deployments have long lifetimes and high staff turnover. An environment that exists only as accumulated manual changes cannot be rebuilt after a disaster, and disaster recovery that depends on someone's memory is not disaster recovery.
GitOps adds a useful property for governance: the Git history is the change record. Who changed what, when, reviewed by whom — the audit trail a health regulator asks for, produced as a by-product.
Supply chain
Health platforms tend to be large, old and dependency-rich. OpenMRS, DHIS2 and HAPI FHIR each pull in hundreds of transitive dependencies.
SBOM — a software bill of materials (CycloneDX or SPDX) listing every component and version. Generate one per build and store it with the artefact. Its value appears on the day a widely used library is found vulnerable and someone asks whether you are affected: with SBOMs, the answer takes minutes. Without them, it takes weeks.
Scanning:
| Scan | Catches | Tools |
|---|---|---|
| Dependency | Known CVEs in libraries | Trivy, Grype, Dependabot, OWASP Dependency-Check |
| Container image | OS package and library CVEs | Trivy, Grype, Clair |
| Secrets | Credentials in source | gitleaks, trufflehog |
| IaC | Insecure infrastructure configuration | Checkov, tfsec, KICS |
| SAST | Code-level flaws | Semgrep, CodeQL |
| DAST | Runtime vulnerabilities | OWASP ZAP |
Provenance. Sign images (Sigstore/cosign) and verify signatures at deployment, so that only artefacts your pipeline built can run.
Set a policy for what blocks a release. "No critical or high vulnerabilities in internet-facing components" is enforceable; "no vulnerabilities" is not, and a policy nobody can meet is ignored entirely.
Secrets
No secrets in source control, container images, or environment files committed anywhere. Use a secrets manager (Vault, OpenBao, or the cloud provider's), inject at runtime, prefer short-lived dynamic credentials, and rotate on staff departure.
Scan for committed secrets in CI and across history — secrets committed and then removed remain in the Git history and remain compromised. Rotate anything found; deleting the commit is not remediation.
Change control for clinical systems
Continuous deployment is appropriate for a reporting dashboard and inappropriate for a prescribing module. Tier your change process by clinical risk:
| Tier | Example | Process |
|---|---|---|
| Low | Dashboard, documentation, reporting query | Automated deployment on merge |
| Medium | Data capture form, non-clinical workflow | Automated, with staged rollout and monitoring |
| High | Clinical decision support, prescribing, terminology release | Clinical review, scheduled release, explicit approval, rehearsed rollback |
Terminology and value set releases belong in the high tier, and are commonly treated as data rather than as change. A value set update can silently alter what a decision support rule fires on. Version them, test them, release them deliberately — see terminology services.
Rollback must be tested. Database migrations that cannot be reversed make rollback impossible; design migrations to be backward-compatible so that the previous application version can still run against the new schema.
Environments
At minimum: development, a staging environment that materially resembles production, and production. For an exchange, add a partner sandbox — a persistent environment with synthetic data where point-of-service vendors develop and certify their integrations. Its absence is the most common cause of vendors testing against production.
Separate credentials, separate certificates and separate client registrations per environment. Reusing production credentials in staging is how staging becomes a path into production.
References
- Synthea synthetic patient generator — https://synthetichealth.github.io/synthea/
- OWASP DevSecOps guideline — https://owasp.org/www-project-devsecops-guideline/
- CycloneDX — https://cyclonedx.org/
- SPDX — https://spdx.dev/
- Sigstore — https://www.sigstore.dev/
- Trivy — https://trivy.dev/
- OpenTofu — https://opentofu.org/
- Argo CD — https://argo-cd.readthedocs.io/